package com.imot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.imot.handler.ImotExciption;
import com.imot.mapper.MeasurementInfoMapper;
import com.imot.pojo.dto.*;
import com.imot.pojo.entity.DeviceInfo;
import com.imot.pojo.entity.Dict;
import com.imot.pojo.entity.MeasurementDetails;
import com.imot.pojo.entity.MeasurementInfo;
import com.imot.pojo.vo.MeasurementDeatilVo;
import com.imot.pojo.vo.MeasurementListVo;
import com.imot.pojo.vo.MeasurementSpecificsVo;
import com.imot.response.Result;
import com.imot.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * ClassName: MonitoringServiceImpl
 * Description:
 * date: 2023/11/18 15:42
 *
 * @author imot-jiah.wang
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MonitoringServiceImpl implements MonitoringService {
    private final IDeviceInfoService deviceInfoService;
    private final IMeasurementInfoService measurementInfoService;
    private final IMeasurementDetailsService measurementDetailsService;
    private final IDictService dictService;

    private final MeasurementInfoMapper measurementInfoMapper;

    @Override
    public Result evaluateMethodActivity(MonitoringDto monitoringDto) {
        PageHelper.startPage(monitoringDto.getPage(),monitoringDto.getLimit());
        LambdaQueryWrapper<DeviceInfo> deviceInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deviceInfoLambdaQueryWrapper.eq(DeviceInfo::getIsDeleted,0);
        LocalDate startTime = monitoringDto.getStartTime();
        LocalDate endTime = monitoringDto.getEndTime();
        String deviceName = monitoringDto.getDeviceName();
        String deviceType = monitoringDto.getDeviceType();
        if (startTime!=null){
            deviceInfoLambdaQueryWrapper.ge(DeviceInfo::getUsageDate,startTime);
        }
        if (endTime!=null){
            deviceInfoLambdaQueryWrapper.le(DeviceInfo::getUsageDate,endTime);
        }
        if (deviceName!=null){
            deviceInfoLambdaQueryWrapper.eq(DeviceInfo::getDeviceName,deviceName);
        }
        if (deviceType!=null){
            deviceInfoLambdaQueryWrapper.eq(DeviceInfo::getDeviceType,deviceType);
        }
        List<DeviceInfo> list = deviceInfoService.list(deviceInfoLambdaQueryWrapper);

        return Result.success(list);
    }

    @Override
    public Result addNewDevice(NewDeviceDto newDeviceDto) {
        DeviceInfo deviceInfo = new DeviceInfo();
        BeanUtils.copyProperties(newDeviceDto,deviceInfo);

        deviceInfoService.save(deviceInfo);
        return Result.success();
    }

    @Override
    public Result getDeviceInfo(Integer deviceId) {
        DeviceInfo deviceInfo = deviceInfoService.getById(deviceId);
        if (deviceInfo==null)throw new ImotExciption(500,"找不到该设备，请检查后重新查询");
        return Result.success(deviceInfo);
    }

    @Override
    public Result deleteDeviceInfo(Integer deviceId) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setId(deviceId);
        deviceInfo.setIsDeleted(1);
        deviceInfoService.updateById(deviceInfo);
        return Result.success();
    }

    @Override
    public Result getMeasurementDetails(MeasurementDto measurementDto) {
        LambdaQueryWrapper<Dict> dictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dictLambdaQueryWrapper.gt(Dict::getId,50000);
        dictLambdaQueryWrapper.lt(Dict::getId,60000);
        List<Dict> dickList = dictService.list(dictLambdaQueryWrapper);

        LambdaQueryWrapper<Dict> dictLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        dictLambdaQueryWrapper1.gt(Dict::getId,60000);
        dictLambdaQueryWrapper1.lt(Dict::getId,70000);
        List<Dict> dictList = dictService.list(dictLambdaQueryWrapper1);
        List<MeasurementListVo> measurementListVo = measurementInfoMapper.getMeasurementListVo(measurementDto);
        for (MeasurementListVo listVo : measurementListVo) {
            String measurementStatus = listVo.getMeasurementStatus();
            for (Dict dict : dickList) {
                if ((String.valueOf(dict.getValue()).equals(measurementStatus))) measurementStatus=dict.getName();
            }

            for (Dict dict : dictList) {
                String reminderFlag = listVo.getReminderFlag();
                if (String.valueOf(dict.getValue()).equals(reminderFlag)) {
                    listVo.setReminderFlag(dict.getName());
                }
            }
            listVo.setLastMeasurementDate(listVo.getMeasurementDate());

            if (!listVo.getMeasurementStatus().equals("2")){
                LocalDate now = LocalDate.now();
                LocalDate createDate = listVo.getCreateDate();
                Integer measurementCycle = listVo.getMeasurementCycle();
                LocalDate date = createDate.minusDays(measurementCycle);
                while (date.isAfter(now)){
                    date.minusDays(measurementCycle);
                }

                listVo.setExpiryDate(date);
            }


        }

        return Result.success(measurementListVo);
    }

    @Override
    public Result getMeasurementSpecifics(Integer id) {
        MeasurementInfo measurementInfo = measurementInfoService.getById(id);
        LambdaQueryWrapper<MeasurementDetails> measurementDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        measurementDetailsLambdaQueryWrapper.eq(MeasurementDetails::getId,id);



        List<MeasurementDetails> list = measurementDetailsService.list(measurementDetailsLambdaQueryWrapper);
        ArrayList<MeasurementDeatilVo> measurementDeatilVos = new ArrayList<>();
        for (MeasurementDetails measurementDetails : list) {
            MeasurementDeatilVo measurementDeatilVo = new MeasurementDeatilVo();
            BeanUtils.copyProperties(measurementDetails,measurementDeatilVo);
            measurementDeatilVos.add(measurementDeatilVo);
        }

        MeasurementSpecificsVo measurementSpecificsVo = new MeasurementSpecificsVo();
        BeanUtils.copyProperties(measurementInfo,measurementSpecificsVo);
        measurementSpecificsVo.setMeasurementDeatilVos(measurementDeatilVos);

        LambdaQueryWrapper<Dict> dictLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dictLambdaQueryWrapper.gt(Dict::getId,50000);
        dictLambdaQueryWrapper.lt(Dict::getId,60000);
        List<Dict> dickList = dictService.list(dictLambdaQueryWrapper);

        LambdaQueryWrapper<Dict> dictLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        dictLambdaQueryWrapper1.gt(Dict::getId,60000);
        dictLambdaQueryWrapper1.lt(Dict::getId,70000);
        List<Dict> dictList = dictService.list(dictLambdaQueryWrapper1);
        for (Dict dict : dickList) {
            String measurementStatus = measurementSpecificsVo.getMeasurementStatus();
            if ((String.valueOf(dict.getValue()).equals(measurementStatus))) measurementSpecificsVo.setMeasurementStatus(dict.getName());
        }

        for (Dict dict : dictList) {
            String reminderFlag = measurementSpecificsVo.getReminderFlag();
            if (String.valueOf(dict.getValue()).equals(reminderFlag)) {
                measurementSpecificsVo.setReminderFlag(dict.getName());
            }
        }
        return Result.success(measurementSpecificsVo);
    }

    @Override
    public Result deleteMeasurement(Integer id) {
        MeasurementInfo measurementInfo = new MeasurementInfo();
        measurementInfo.setId(id);
        measurementInfo.setIsDeleted(1);
        measurementInfoService.updateById(measurementInfo);
        return Result.success();
    }

    @Transactional
    @Override
    public Result updateMeasurement(UpdateMeasurementDto updateMeasurementDto) {
        Integer id = updateMeasurementDto.getId();

        List<UpdateMeasurementDetailDto> updateMeasurementDetailDtoList = updateMeasurementDto.getUpdateMeasurementDetailDtoList();
        for (UpdateMeasurementDetailDto updateMeasurementDetailDto : updateMeasurementDetailDtoList) {
            if (updateMeasurementDetailDto.getId() == null){
                MeasurementDetails measurementDetails = new MeasurementDetails();
                BeanUtils.copyProperties(updateMeasurementDetailDto,measurementDetails);
                measurementDetails.setMeasurementInfoId(id);
                measurementDetailsService.save(measurementDetails);
                continue;
            }

            MeasurementDetails measurementDetails = new MeasurementDetails();
            BeanUtils.copyProperties(updateMeasurementDetailDto,measurementDetails);
            measurementDetailsService.updateById(measurementDetails);
        }

        MeasurementInfo measurementInfo = new MeasurementInfo();
        BeanUtils.copyProperties(updateMeasurementDto,measurementInfo);
        measurementInfoService.updateById(measurementInfo);

        List<Integer> deleteMeasurementDetailIds = updateMeasurementDto.getDeleteMeasurementDetailIds();

        measurementDetailsService.removeByIds(deleteMeasurementDetailIds);
        return Result.success();
    }
}

